package app.domain.geojson;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.PrecisionModel;

import java.util.Arrays;

public class GeoPointDTO {
    private String type;
    private Double[] coordinate;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public Double[] getCoordinate() {
        return coordinate;
    }

    public void setCoordinate(Double[] coordinate) {
        this.coordinate = coordinate;
    }

    public GeoPointDTO(Double[] coordinate) {
        this.type = "Point";
        this.coordinate = coordinate;
    }

    public GeoPointDTO(String type, Double[] coordinate) {
        this.type = type;
        this.coordinate = coordinate;
    }

    public GeoPointDTO() {
        this.type = "Point";
        this.coordinate = new Double[]{ 0.0, 0.0 };
    }

    /**
     * 已知的Bug: GeoJSON字符串内如果包含crs投影坐标系字段，则无法解析。
     * "crs":{"type":"name","properties":{"name":"EPSG:3857"}},
     *
     * 目前只能解析下列第一种GeoJSON字符串
     *
     * {"type":"Point","coordinates":[113.887165,22.4476893]}
     *
     * {"type":"Point","crs":{"type":"name","properties":{"name":"EPSG:3857"}},"coordinates":[12677861.215689527,2565361.251024475]}
     *
     * @param json GeoJSON字符串
     * @return 被解析后的坐标点结构体
     */
    public static GeoPointDTO fromJsonStr(String json) {
        ObjectMapper objectMapper;
        GeoPointDTO dto;

        objectMapper = new ObjectMapper();
        dto = null;
        try {
            dto = objectMapper.readValue(json, GeoPointDTO.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return dto;
    }

    public static GeoPointDTO fromGeometry(Geometry geom) {
        GeometryFactory f;
        Point p;
        GeoPointDTO dto;
        if ("Point".compareToIgnoreCase(geom.getGeometryType()) != 0) {
            return new GeoPointDTO();
        }
        PrecisionModel precisionModel;

        precisionModel = new PrecisionModel(PrecisionModel.FIXED);
        f = new GeometryFactory(precisionModel, geom.getSRID());
        p = f.createPoint(geom.getCoordinate());
        dto = new GeoPointDTO("Point",
                new Double[] { p.getX(), p.getY() }
        );
        return dto;
    }

    @Override
    public String toString() {
        return "type=" + type + ", coordinate=" + Arrays.toString(coordinate);
    }
}
